package cn.legend.travel.basic.info.config;

import cn.legend.travel.basic.info.filter.JwtAuthorizationFilter;
import cn.legend.travel.common.web.JsonResult;

import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.io.PrintWriter;

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Autowired
    private JwtAuthorizationFilter jwtAuthorizationFilter;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        System.out.println("进入securityConfiguration");
        // Cross-Origin Resource Sharing启用CorsFilter，将会对OPTIONS类型请求放行
        http.cors();

        //处理未通过认证时的错误
        http.exceptionHandling().authenticationEntryPoint((httpServletRequest, response, e) -> {
            response.setContentType("application/json;charset=utf-8");
            String message="您当前未登录！请登录!";
            JsonResult jsonResult=JsonResult.
                    fail(cn.legend.travel.common.enumerator.ServiceCode.ERROR_UNAUTHORIZED,message);
            PrintWriter printWriter=response.getWriter();
            printWriter.println(JSON.toJSONString(jsonResult));
            printWriter.close();
            return;
        });

        // 当使用JWT后，可以配置Spring Security不再使用Session
        // SessionCreationPolicy.NEVER：从不主动创建Session，但是，如果Session已经存在，仍会自动使用Session
        // SessionCreationPolicy.STATELESS：无状态的，无论是否存在Session，都不会使用Session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        // 将解析JWT的过滤器添加到Spring Security的过滤器链中比较早期执行的位置
        http.addFilterBefore(jwtAuthorizationFilter, UsernamePasswordAuthenticationFilter.class);

        // 调用formLogin()方法，表示启用登录表单页，不调用则不启用
        // 当未通过认证，却尝试访问需要认证的资源时：
        // -- 如果启用了登录表单页，则自动重定向到登录表单页
        // -- 如果未启用登录表单页，则响应403
//        http.formLogin();

        // 白名单，使用AntStyle模式
        // 使用1个星号，通配某个层级下的任意名称或资源，例如：/admin/* 可以通配：/admin/list或/admin/add-new，但不可以匹配到：/admin/9527/delete
        // 使用2个星号，通配若干层级下的任意名称或资源，例如：/admin/** 可以通配：/admin/list或/admin/add-new，也可以匹配到：/admin/9527/delete
        String[] urls={
                "/doc.html",
                "/**/*.css",
                "/**/*.js",
                "/swagger-resources",
                "/v2/api-docs"
        };
        http.authorizeRequests()
                .mvcMatchers(urls)
                .permitAll()
                .anyRequest()
                .authenticated();
        // 关闭“防止伪造跨域攻击的防御机制”
        http.csrf().disable();
    }
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

}
